Skip to content

Prod: harden program project access and expert filters - #732

Merged
TThanos3000 merged 1 commit into
masterfrom
prod/project-program-read-access
Sep 9, 2026
Merged

TThanos3000 merged 1 commit into
masterfrom
prod/project-program-read-access

Conversation

@TThanos3000

Copy link
Copy Markdown
Collaborator

Основа и границы

  • Exact master base: 295d85f34b62390aa347fa63b7f23da8b057d2f9, подтверждён после git fetch origin; совпадает с SHA аудита.
  • Exact head: 8e3cd2d89f1e42a6457f3e924b75d7cf8bba5e76.
  • DEV #722 и #727 использованы только как reference. Это semantic production port, не cherry-pick и не merge dev -> master.
  • Только backend. Модели, migrations, зависимости, workflows, Docker, Angular и React не изменены.

Причины и исправления

  1. 403 для draft Project: ProjectVisibilityPermission разрешал manager/expert связанной программы, но следующий HasInvolvementInProjectOrReadOnly снова запрещал READ без project-level involvement. Добавлена отдельная ветка только для SAFE_METHODS и общий read helper.
  2. MultipleObjectsReturned: singular ProjectDetailSerializer.get_partner_program() использовал .get() при возможных нескольких PartnerProgramProject. Теперь выбор детерминированный.
  3. Multi-program disclosure: обычный minimum global link мог раскрыть program fields/values чужой программы. Для program-role readers выбирается minimum PK только среди eligible links.

Точная READ / WRITE policy

  • Leader, collaborator, существующее invite involvement, staff и superuser: READ разрешён; singular partner_program выбирается по минимальному глобальному PartnerProgramProject PK.
  • Manager/expert без независимого project-level access: READ общего Project разрешён через любую связанную программу; вложенные program_fields/program_field_values только из программы, где этот user manager либо expert. При нескольких eligible links выбирается минимальный PK среди них.
  • Это ограничение program-role selection действует и для public published Project.
  • При отсутствии links: partner_program: null.
  • Existing public/non-draft READ сохраняется; public flag сам по себе не открывает draft.
  • PATCH/PUT/DELETE не получают новых grants. Старые WRITE-ветки и timing rules сохранены; AST-сравнение нижележащих WRITE-веток с base совпало. Manager/expert с независимым collaborator/invite involvement сохраняет именно старые project-level права.
  • projects/views.py, в том числе production PATCH -> PATCH, не изменён.

Expert filter schema

Только существующий GET /programs/<id>/filters/ использует новый узкий permission:

  • anonymous 401;
  • participant/outsider и expert/manager только другой программы 403;
  • expert этой программы, её manager, staff/superuser 200.
    Response/filtering semantics не меняются. Endpoint остаётся GET-only: mutation methods для допущенных пользователей возвращают 405. Другие manager endpoints, включая manager-overview, projects/filter и export, экспертам не открыты.
    Missing program сохраняет production statuses: staff/superuser 404, остальные authenticated 403, anonymous 401.

Public data exposure: существующий контракт

На base опубликованный public Project с одной program link уже отдаёт program_fields и program_field_values anonymous/outsider через singular serializer. Это не исправлено молча: сохранено и зафиксировано regression-тестом. Данная защита не делает уже публичные ответы приватными; отдельное изменение public contract требует согласования.
Главная закрытая regression: private/draft multi-program Project не раскрывает поля чужой программы читателю, получившему доступ только по program role.

Проверки и SQL

Добавлены 20 regression-тестов (часть с subTest-матрицами):

  • filters: roles, неизменённый payload, read-only, другие manager API, missing ID;
  • project: private/draft/public, GET/HEAD/OPTIONS, forbidden PATCH/PUT/DELETE и независимые WRITE права;
  • 0/1/multiple links, minimum eligible/global PK, полные вложенные fields/values, public exposure;
  • SQL при 1 и 8 links.

На локальном PostgreSQL 18.1 / Python 3.11.15, с procollab.settings_ci и изолированной тестовой БД:

Проверка Результат
Новые tests + existing program filters 31/31
Все projects + partner_programs regression 692/692
Полный backend suite 1261/1261: unittest OK; затем exit 1 только на удалении тестовой БД
Django check / check --tag models Пройдены
makemigrations --check --dry-run No changes detected
Black --check по 7 изменённым Python-файлам Пройден
Полный flake8 Пройден
git diff --check Пройден

Локальное ограничение cleanup: после Ran 1261 tests ... OK Django получил OperationalError при DROP изолированной test_procollab_read_2606b0d1: на тот момент 21 оставшееся соединение. После завершения процесса соединений осталось 0; удалена только эта тестовая БД, без принудительного завершения чужих sessions. Test infrastructure не изменялась. Локальный exit 1 не скрыт; считать весь локальный command полностью зелёным нельзя. На PostgreSQL CI полный command, включая cleanup, завершился успешно.

После прогрева View/ContentType/cache полный detail request:

Reader 1 link 8 links
Leader 19 SQL 19 SQL
Manager 30 SQL 30 SQL
Expert 30 SQL 30 SQL

Нет SQL-запросов в цикле по links; сериализуется одна выбранная связь. Часть diff существующих файлов является только нормализацией Black, без изменения соседней логики.

GitHub PostgreSQL CI: успешный run на exact head, PostgreSQL 15 / Python 3.11: 86 locking/constraint tests и полный suite 1261/1261. Выполнены checks, применение существующих migrations и очистка тестовой БД. Workflow запускался только на feature-ветке, не на master.

Дополнительный push CI: на последней проверке перед созданием PR Lint прошёл, Tests ещё выполнялся. Это отдельно от уже успешного PostgreSQL CI на том же head.

Production compatibility

Application / Team / Submission / SubmissionExpertAssignment / Evaluation и их endpoints/permissions/migrations не изменены. /programs/<id>/manager-overview/ не меняется. Не добавлены analytics, case/canonical fields API, current_project_application, evaluation deadline, новые endpoint/query params или массив partner_programs.
Production vacancy/news/application/evaluation изменения сохранены; полный regression проверяет их вместе с port.

Draft для review. Не merge. Не deploy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants